﻿#include "stdafx.h"

#include "svgpalette.h"

#include <array>

#include <QColorDialog>

constexpr std::array<char[10], 100> COLOR_TABLE{
	"#444444",
	"#482816",
	"#422C10",
	"#3B2F0E",
	"#32320F",
	"#293414",
	"#1F361B",
	"#153723",
	"#0C372C",
	"#083734",
	"#0E353B",
	"#1A333F",
	"#273141",
	"#332D40",
	"#3E2A3C",
	"#462735",
	"#4B252D",
	"#4D2425",
	"#4C261D",
	"#666666",
	"#845335",
	"#7B572D",
	"#6F5C2A",
	"#62612C",
	"#546433",
	"#46673D",
	"#396849",
	"#306856",
	"#2D6862",
	"#33666C",
	"#426373",
	"#535F75",
	"#645A73",
	"#74556D",
	"#805064",
	"#884D58",
	"#8B4D4B",
	"#894F3F",
	"#999999",
	"#C48157",
	"#B8874D",
	"#A98E49",
	"#97944B",
	"#849854",
	"#729C62",
	"#619E73",
	"#559E84",
	"#529D94",
	"#5B9BA2",
	"#6D97AB",
	"#8391AE",
	"#9A8AAB",
	"#AF84A3",
	"#BF7E96",
	"#C97A86",
	"#CE7975",
	"#CC7C65",
	"#BBBBBB",
	"#FFB27C",
	"#FABA6F",
	"#E6C36A",
	"#CFCA6D",
	"#B8D078",
	"#A0D58A",
	"#8CD79F",
	"#7DD8B5",
	"#7AD6CA",
	"#84D3DB",
	"#9ACEE6",
	"#B6C7EA",
	"#D3BEE7",
	"#EDB6DC",
	"#FFAFCC",
	"#FFAAB8",
	"#FFA9A2",
	"#FFAC8D",
	"#DDDDDD",
	"#FFE7A2",
	"#FFF093",
	"#FFFA8D",
	"#FFFF91",
	"#EEFF9F",
	"#D1FFB4",
	"#B9FFCE",
	"#A8FFE9",
	"#A4FFFF",
	"#B1FFFF",
	"#CBFFFF",
	"#EDFFFF",
	"#FFF5FF",
	"#FFEBFF",
	"#FFE2FF",
	"#FFDCEC",
	"#FFDBD2",
	"#FFDFB8",
};

constexpr int PALETTE_HEIGHT = 36;

constexpr int TARGET_CHOOSE_BLOCK_SIZE = 22;
constexpr int TARGET_CHOOSE_WIDGET_WIDTH = 40;

constexpr int COLOR_PICKER_WIDTH = 400;
constexpr int COLOR_BLOCK_LINE_COLOR = 19;
constexpr int COLOR_BLOCK_LINE = 5;
constexpr int COLOR_BLOCK_WIDTH = COLOR_PICKER_WIDTH / COLOR_BLOCK_LINE_COLOR;
constexpr int COLOR_BLOCK_HEIGHT = PALETTE_HEIGHT / COLOR_BLOCK_LINE;
constexpr int COLOR_PICKER_HEIGHT = COLOR_BLOCK_LINE * COLOR_BLOCK_HEIGHT; // 因为精度问题，这个可能和 PALETTE_HEIGHT 不同

SvgPalette::SvgPalette(QWidget *parent)
	: QWidget(parent)
{
	setFixedSize(COLOR_PICKER_WIDTH + TARGET_CHOOSE_WIDGET_WIDTH, PALETTE_HEIGHT);
}

void SvgPalette::ChangeColor(const QColor &inner, const QColor &line)
{
	m_lineColor = line;
	m_innerColor = inner;
	update();
}

void SvgPalette::paintEvent(QPaintEvent *event)
{
	QPainter painter(this);

	_PaintTargetBlock(painter);

	painter.translate(TARGET_CHOOSE_WIDGET_WIDTH, 0);
	_PaintColorPicker(painter);

	QWidget::paintEvent(event);
}

void SvgPalette::mousePressEvent(QMouseEvent *event)
{
	if (event->localPos().x() < TARGET_CHOOSE_WIDGET_WIDTH)
	{
		if (event->buttons() & Qt::LeftButton)
		{
			if (m_target == SvgColorTarget::Inner)
				m_target = SvgColorTarget::Line;
			else
				m_target = SvgColorTarget::Inner;
			update();
		}
		else if (event->buttons() & Qt::RightButton)
		{
			const QColor color = QColorDialog::getColor(_GetTargetColor(), this,
														tr("chose a color"), QColorDialog::ShowAlphaChannel);
			if (color.isValid())
			{
				_GetTargetColor() = color;
				update();
				emit ColorChanged(color, m_target);
			}
		}
	}
	else if (event->localPos().x() < TARGET_CHOOSE_WIDGET_WIDTH + COLOR_PICKER_WIDTH && event->localPos().y() < COLOR_PICKER_HEIGHT)
	{
		const QColor color = _GetColorByPos(event->localPos());
		_GetTargetColor() = color;
		update();
		emit ColorChanged(color, m_target);
	}
	QWidget::mousePressEvent(event);
}

void SvgPalette::_PaintColorPicker(QPainter &painter)
{
	painter.save();
	for (int i = 0; i < COLOR_BLOCK_LINE; ++i)
	{
		for (int j = 0; j < COLOR_BLOCK_LINE_COLOR; ++j)
		{
			QColor blockColor = _GetColorByIndex(j, i);
			painter.setPen(blockColor);
			painter.setBrush(blockColor);
			painter.drawRect(j * COLOR_BLOCK_WIDTH, i * COLOR_BLOCK_HEIGHT, COLOR_BLOCK_WIDTH, COLOR_BLOCK_HEIGHT);
		}
	}
	painter.restore();
}

void SvgPalette::_PaintTargetBlock(QPainter &painter) const
{
	constexpr double targetSizeHalf = TARGET_CHOOSE_BLOCK_SIZE / 2.0;
	painter.translate(targetSizeHalf, targetSizeHalf);
	m_target == SvgColorTarget::Inner ? _PaintLineBlock(painter) : _PaintInnerBlock(painter);
	painter.translate(-targetSizeHalf, -targetSizeHalf);
	m_target == SvgColorTarget::Inner ? _PaintInnerBlock(painter) : _PaintLineBlock(painter);
}

void SvgPalette::_PaintLineBlock(QPainter &painter) const
{
	painter.save();
	painter.setBrush(m_lineColor);
	painter.drawRect(0, 0, TARGET_CHOOSE_BLOCK_SIZE, TARGET_CHOOSE_BLOCK_SIZE);
	painter.setBrush(Qt::white);

	constexpr int innerBlockSize = TARGET_CHOOSE_BLOCK_SIZE / 3;
	painter.drawRect(innerBlockSize, innerBlockSize, innerBlockSize, innerBlockSize);
	painter.restore();
}

void SvgPalette::_PaintInnerBlock(QPainter &painter) const
{
	painter.save();
	painter.setBrush(m_innerColor);
	painter.drawRect(0, 0, TARGET_CHOOSE_BLOCK_SIZE, TARGET_CHOOSE_BLOCK_SIZE);
	painter.restore();
}

QColor SvgPalette::_GetColorByIndex(int x, int y)
{
	return COLOR_TABLE[x + y * COLOR_BLOCK_LINE_COLOR];
}

QColor SvgPalette::_GetColorByPos(const QPointF &p)
{
	return _GetColorByIndex((p.x() - TARGET_CHOOSE_WIDGET_WIDTH) / COLOR_BLOCK_WIDTH, p.y() / COLOR_BLOCK_HEIGHT);
}

QColor &SvgPalette::_GetTargetColor()
{
	if (m_target == SvgColorTarget::Line)
		return m_lineColor;
	return m_innerColor;
}
